package com.gitee.huanminabc.jcommon.test;


import com.gitee.huanminabc.jcommon.exception.CommonException;
import com.gitee.huanminabc.jcommon.exception.StackTraceUtil;
import com.gitee.huanminabc.jcommon.multithreading.executor.ThreadFactoryUtil;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

/**
 * 测试线程工具类
 * @Author huanmin
 * @Date 2024/6/6 下午6:38
 */
public class ExecutorTestUtil {
    //配合  public static void create(int n, Runnable runnable) 使用 主要是为了测试
    public static AtomicInteger busyThreadNum = new AtomicInteger(0);


    public static void create(int n, Consumer<Integer> runnable) {
        busyThreadNum.addAndGet(n);
        String className = getThreadName();
        ThreadPoolExecutor executor = ThreadFactoryUtil.getExecutor(className);
        for (int i = 1; i <= n; i++) {
            int finalI = i;
            executor.submit(()->{
                try {
                    runnable.accept(finalI);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                } finally {
                    busyThreadNum.decrementAndGet();
                }
            });
        }
    }

    //创建n线并执行Runnable, 不等待全部线程执行完毕
    public static void create(int n, Runnable runnable) {
        busyThreadNum.addAndGet(n);
        String className = getThreadName();
        ThreadPoolExecutor executor = ThreadFactoryUtil.getExecutor(className);
        for (int i = 0; i < n; i++) {
            executor.submit(()->{
                try {
                    runnable.run();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                } finally {
                    busyThreadNum.decrementAndGet();
                }
            });
        }
    }
    //等待全部线程执行完毕
    public static void waitAll() {
        while (busyThreadNum.get()!=0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new CommonException(e);
            }
        }
    }
    public static void createAndWaitAll(int n, Consumer<Integer> runnable) {
        String className = getThreadName();
        ThreadPoolExecutor executor = ThreadFactoryUtil.getExecutor(className);
        CountDownLatch countDownLatch = new CountDownLatch(n);
        for (int i = 1; i <=n; i++) {
            int finalI = i;
            executor.submit(() -> {
                try {
                    runnable.accept(finalI);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new CommonException(e);
        }
    }


    //创建n线并执行Runnable, 等待全部线程执行完毕
    public static void createAndWaitAll(int n, Runnable runnable) {
        String className = getThreadName();
        ThreadPoolExecutor executor = ThreadFactoryUtil.getExecutor(className);
        CountDownLatch countDownLatch = new CountDownLatch(n);
        for (int i = 0; i < n; i++) {
            executor.submit(() -> {
                try {
                    runnable.run();
                } catch (Exception e) {
                    e.printStackTrace();
                   System.exit(1);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new CommonException(e);
        }
    }

    //创建n线并执行Callable, 等待全部线程执行完毕
    public static <T> List<T> createAndWaitAll(int n, Callable<T> callable) {
        String className = getThreadName();
        ThreadPoolExecutor executor = ThreadFactoryUtil.getExecutor(className);
        CountDownLatch countDownLatch = new CountDownLatch(n);
        List<T> results = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            executor.submit(() -> {
                try {
                    results.add(callable.call());
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new CommonException(e);
        }
        return results;
    }


    //获取调用方的类名
    private static  String getThreadName(){
        return StackTraceUtil.stackTraceLevel(4).getClassName();
    }
}
